package com.globefrog.framework.juc.executor;


import com.globefrog.framework.log.LogHelper;
import com.globefrog.framework.log.handler.ErrorHandler;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;

/**
 * 线程池抽象类.
 *
 * @author : caijinbang
 * @date : Create in 2021-01-30
 */
public abstract class BaseExecutor {

  protected ExecutorService executorService;
  @Autowired
  private ApplicationContext applicationContext;
  @Autowired
  protected LogHelper logHelper;
  @Autowired
  protected ErrorHandler errorHandler;


  public BaseExecutor(ExecutorService executorService) {
    this.executorService = executorService;
  }

  /**
   * 将当前bean初始化到Spring上线文中. AutowireCapableBeanFactory作用
   * 1、为已经实例化的对象装配属性，这些属性对象都是Spring管理的；
   * 2、实例化一个类型，并自动装配，这些属性对象都是Spring管理的，实例话的类不被Spring管理。
   *
   * @param bean properties
   * @param <T>  properties
   * @return properties
   */
  protected <T> T initBean(T bean) {
    if (inSpringContext(bean)) {
      return bean;
    } else {
      AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
      beanFactory.autowireBean(bean);
      return (T) beanFactory.initializeBean(bean, bean.getClass().getName());
    }
  }

  /**
   * 判断当前bean是否已经实现类InitializingBean.
   *
   * @param bean properties
   * @return 是否已经是Spring properties
   */
  private boolean inSpringContext(Object bean) {
    return bean instanceof InitializingBean;
  }


  /**
   * 主动执行任务的近似线程数.
   *
   * @return 主动执行任务的近似线程数
   */
  public int getActiveCount() {
    return ((ThreadPoolExecutor) executorService).getActiveCount();
  }

  /**
   * 线程池中的当前线程数.
   *
   * @return 线程池中的当前线程数
   */
  public int getPoolSize() {
    return ((ThreadPoolExecutor) executorService).getPoolSize();
  }

  /**
   * 计划执行的近似任务总数.
   *
   * @return 曾计划执行的近似任务总数
   */
  public long getTaskCount() {
    return ((ThreadPoolExecutor) executorService).getTaskCount();
  }

  /**
   * 此执行程序使用的任务队列.
   *
   * @return 此执行程序使用的任务队列
   */
  public long getQueueSize() {
    BlockingQueue<Runnable> queue = ((ThreadPoolExecutor) executorService).getQueue();
    return queue == null ? 0L : (long) queue.size();
  }

  /**
   * 此执行程序使用的任务队列.
   *
   * @return 此执行程序使用的任务队列
   */
  public BlockingQueue<Runnable> getQueue() {
    return ((ThreadPoolExecutor) executorService).getQueue();
  }

  /**
   * 已完成执行的近似任务总数.
   *
   * @return 已完成执行的近似任务总数
   */
  public long getCompletedTaskCount() {
    return ((ThreadPoolExecutor) executorService).getCompletedTaskCount();
  }

  /**
   * 最大线程池大小.
   *
   * @return 最大线程池大小
   */
  public int getMaximumPoolSize() {
    return ((ThreadPoolExecutor) executorService).getMaximumPoolSize();
  }

  /**
   * 线程数历史高峰线.
   *
   * @return 线程数历史高峰线
   */
  public int getLargestPoolSize() {
    return ((ThreadPoolExecutor) executorService).getLargestPoolSize();
  }

  /**
   * 核心线程池大小.
   *
   * @return 核心线程池大小
   */
  public int getCorePoolSize() {
    return ((ThreadPoolExecutor) executorService).getCorePoolSize();
  }

  /**
   * 关闭线程.Spring shutdown时bean销毁调用
   */
  protected void shutdown() {
    if (executorService != null) {
      executorService.shutdown();
      executorService = null;
    }
  }

  /**
   * 立即关闭线程.Spring shutdown时bean销毁调用
   */
  protected void shutdownNow() {
    if (executorService != null) {
      List<Runnable> runnables = executorService.shutdownNow();

      for (Runnable runnable : runnables) {
        if (runnable instanceof Future) {
          ((Future) runnable).cancel(Boolean.TRUE);
        }
      }
      executorService = null;
    }
  }

  /**
   * 是否正在运行.
   *
   * @return 运行状态
   */
  protected boolean isRunning() {
    return executorService != null && !executorService.isShutdown();
  }
}
